package com.redepronik.negosyscom.invfac.controller;

import static com.redepronik.negosys.utils.Utils.*;


import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import org.primefaces.event.SelectEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.redepronik.negosys.invfac.entity.Credito;
import com.redepronik.negosys.invfac.entity.Detallecredito;
import com.redepronik.negosys.invfac.entity.Egreso;
import com.redepronik.negosys.invfac.entity.Garante;
import com.redepronik.negosys.invfac.service.EgresoService;
import com.redepronik.negosys.rrhh.entity.Persona;
import com.redepronik.negosys.rrhh.service.ClienteService;

@Controller
@Scope("session")
public class CreditoBean implements Serializable {

	private static final long serialVersionUID = 1L;

	@Autowired
	private EgresoService egresoService;

	@Autowired
	private ClienteService clienteService;

	// /
	private List<Egreso> listaEgresos;
	private String criterioBusquedaCliente;
	private String criterioBusquedaCodigo;
	// /

	// /
	private List<Persona> listaGarantesBusqueda;
	private String criterioBusqueda;
	// /

	private Egreso egreso;
	private Credito credito;
	private Date fechaInicio;
	private BigDecimal montoCredito;

	private List<Persona> listaGarantes;
	private Persona garante;

	private boolean bnCredito;
	private boolean bnGuardar;

	public CreditoBean() {
		limpiarObjetos();
	}

	public void actualizar(ActionEvent actionEvent) {
		if (listaGarantes != null && !listaGarantes.isEmpty()) {
			credito.setGarantes(new ArrayList<Garante>());
			for (Persona p : listaGarantes) {
				Garante g = new Garante();
				g.setCliente(p.getCliente());
				credito.addGarante(g);
			}
		}

		credito.setEgreso(egreso);
		egreso.setCredito(credito);

		egresoService.actualizar(egreso, null);
		presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_INFO,
				"MENSAJE DEL SISTEMA", "INSERTO CREDITO PARA LA FACTURA: "
						+ egreso.getCodigodocumento()));

		limpiarObjetos();

	}

	public void calcularCredito() {
		if (!comprobarCredito()) {
			credito.setMonto(redondearTotales(valorConPorcentaje(montoCredito,
					credito.getInteres())));

			BigDecimal mensual = redondearTotales(divide(credito.getMonto(),
					credito.getMeses()));
			BigDecimal suma = new BigDecimal("0");
			List<BigDecimal> list = new ArrayList<BigDecimal>();
			for (int i = 1; i <= credito.getMeses(); i++) {
				list.add(mensual);
				suma = suma.add(mensual);
			}
			BigDecimal centavos = new BigDecimal("0");
			if (suma.compareTo(credito.getMonto()) > 0) {
				centavos = redondearTotales(suma.subtract(credito.getMonto()));
				list.set(0, list.get(0).subtract(centavos));
			} else if (suma.compareTo(credito.getMonto()) < 0) {
				centavos = redondearTotales(credito.getMonto().subtract(suma));
				list.set(0, list.get(0).add(centavos));
			}

			Calendar calendar = new GregorianCalendar();
			calendar.setTime(fechaInicio);

			Calendar c = new GregorianCalendar();
			c.setTime(fechaInicio);

			credito.setDetallecreditos(new ArrayList<Detallecredito>());
			for (int i = 1; i <= credito.getMeses(); i++) {
				Detallecredito detallescredito = new Detallecredito();
				detallescredito.setOrden(i);
				calendar.add(Calendar.DATE, 30);
				detallescredito.setFechalimite(calendar.getTime());
				detallescredito.setCuota(list.get(i - 1));
				detallescredito.setSaldo(detallescredito.getCuota());
				c.setTime(detallescredito.getFechalimite());
				c.add(Calendar.DATE, 16);
				detallescredito.setFechamora(c.getTime());
				detallescredito.setPagado(false);
				credito.addDetallecredito(detallescredito);
			}

			credito.setPagado(false);

			bnGuardar = false;
		}
	}

	public void cancelarCredito() {
		credito = new Credito();
		fechaInicio = new Date();
		bnGuardar = true;
	}

	public void cargarEgreso(SelectEvent event) {
		credito = new Credito();
		fechaInicio = new Date();

		listaGarantes = new ArrayList<Persona>();
		garante = new Persona();

		bnCredito = true;
		bnGuardar = true;

		egreso = egresoService.obtenerPorEgresoId(egreso.getEgresoid());
		montoCredito = montoCredito();
		bnCredito = false;
	}

	private boolean comprobarCredito() {
		if (credito.getMeses() <= 0) {
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"MENSAJE DEL SISTEMA",
					"LOS MESES NO PUEDEN SER MENORES QUE 1"));
			return true;
		} else if (credito.getInteres().compareTo(new BigDecimal("0")) < 0) {
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"MENSAJE DEL SISTEMA",
					"EL INTERES NO PUEDE SER MENOR QUE CERO"));
			return true;
		} else if (fechaInicio == null) {
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"MENSAJE DEL SISTEMA",
					"TIENE QUE TENER UNA FECHA DE COMIENZO"));
			return true;
		}
		return false;
	}

	public Credito getCredito() {
		return credito;
	}

	public String getCriterioBusqueda() {
		return criterioBusqueda;
	}

	public String getCriterioBusquedaCliente() {
		return criterioBusquedaCliente;
	}

	public String getCriterioBusquedaCodigo() {
		return criterioBusquedaCodigo;
	}

	public Egreso getEgreso() {
		return egreso;
	}

	public Date getFechaInicio() {
		return fechaInicio;
	}

	public Persona getGarante() {
		return garante;
	}

	public List<Egreso> getListaEgresos() {
		return listaEgresos;
	}

	public List<Persona> getListaGarantes() {
		return listaGarantes;
	}

	public List<Persona> getListaGarantesBusqueda() {
		return listaGarantesBusqueda;
	}

	public BigDecimal getMontoCredito() {
		return montoCredito;
	}

	public boolean isBnCredito() {
		return bnCredito;
	}

	public boolean isBnGuardar() {
		return bnGuardar;
	}

	public void limpiarObjetos() {
		egreso = new Egreso();
		credito = new Credito();
		fechaInicio = new Date();
		montoCredito = newBigDecimal();

		listaGarantes = new ArrayList<Persona>();
		garante = new Persona();

		bnCredito = true;
		bnGuardar = true;
	}

	public void limpiarObjetosBusqueda() {
		criterioBusquedaCliente = new String();
		criterioBusquedaCodigo = new String();
		listaEgresos = new ArrayList<Egreso>();
	}

	public void limpiarObjetosBusquedaGarante() {
		criterioBusqueda = new String();
		listaGarantesBusqueda = new ArrayList<Persona>();
	}

	private BigDecimal montoCredito() {
		BigDecimal totalFactura = egresoService.calcularTotal(egreso);

		BigDecimal abonos = egresoService.calcularEntradas(egreso);

		return totalFactura.subtract(abonos);
	}

	public void obtener() {
		if (criterioBusquedaCliente.compareToIgnoreCase("") == 0
				&& criterioBusquedaCodigo.compareToIgnoreCase("") == 0)
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"MENSAJE DEL SISTEMA", "INGRESE UN CRITERIO DE BUSQUEDA"));
		else {
			if (criterioBusquedaCliente.length() >= 1
					&& criterioBusquedaCliente.length() <= 4)
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
						"MENSAJE DEL SISTEMA",
						"INGRESE MAS DE 4 CARACTERES PARA LA BÚSQUEDA POR CLIENTES"));
			else if (!criterioBusquedaCodigo.matches("[0-9]*"))
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
						"MENSAJE DEL SISTEMA",
						"INGRESE SOLO NÚMEROS PARA LA BÚSQUEDA POR DOCUMENTOS"));
			else if (criterioBusquedaCodigo.compareToIgnoreCase("") != 0
					&& criterioBusquedaCodigo.charAt(0) == '0')
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
						"MENSAJE DEL SISTEMA",
						"NO SE PERMITE CEROS AL INICIO PARA LA BÚSQUEDA POR DOCUMENTOS"));
			else {
				listaEgresos = egresoService.obtenerEgresosParaCredito(
						criterioBusquedaCliente.toUpperCase(),
						criterioBusquedaCodigo.toUpperCase());
				criterioBusquedaCliente = new String();
				criterioBusquedaCodigo = new String();
			}
		}
	}

	public void obtenerGarante(SelectEvent event) {
		listaGarantes.add(clienteService.obtenerPorPersonaId(garante
				.getPersonaid()));
	}

	public void obtenerGarantesProBusqueda() {
		if (criterioBusqueda.length() >= 0 && criterioBusqueda.length() <= 3) {
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"MENSAJE DEL SISTEMA", "INGRESE MAS DE 3 CARACTERES"));
		} else {
			listaGarantesBusqueda = clienteService.obtener(criterioBusqueda
					.toUpperCase());
			if (listaGarantesBusqueda.isEmpty()) {
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_WARN,
						"MENSAJE DEL SISTEMA",
						"NO SE ENCONTRO NINGUNA COINCIDENCIA"));
			}
			criterioBusqueda = new String();
		}
	}

	private void presentaMensaje(FacesMessage message) {
		FacesContext.getCurrentInstance().addMessage(null, message);
	}

	public void setBnCredito(boolean bnCredito) {
		this.bnCredito = bnCredito;
	}

	public void setBnGuardar(boolean bnGuardar) {
		this.bnGuardar = bnGuardar;
	}

	public void setCredito(Credito credito) {
		this.credito = credito;
	}

	public void setCriterioBusqueda(String criterioBusqueda) {
		this.criterioBusqueda = criterioBusqueda;
	}

	public void setCriterioBusquedaCliente(String criterioBusquedaCliente) {
		this.criterioBusquedaCliente = criterioBusquedaCliente;
	}

	public void setCriterioBusquedaCodigo(String criterioBusquedaCodigo) {
		this.criterioBusquedaCodigo = criterioBusquedaCodigo;
	}

	public void setEgreso(Egreso egreso) {
		this.egreso = egreso;
	}

	public void setFechaInicio(Date fechaInicio) {
		this.fechaInicio = fechaInicio;
	}

	public void setGarante(Persona garante) {
		this.garante = garante;
	}

	public void setListaEgresos(List<Egreso> listaEgresos) {
		this.listaEgresos = listaEgresos;
	}

	public void setListaGarantes(List<Persona> listaGarantes) {
		this.listaGarantes = listaGarantes;
	}

	public void setListaGarantesBusqueda(List<Persona> listaGarantesBusqueda) {
		this.listaGarantesBusqueda = listaGarantesBusqueda;
	}

	public void setMontoCredito(BigDecimal montoCredito) {
		this.montoCredito = montoCredito;
	}

}